package se.webbzon.oschi01.metric;

public class JaroWinklerMetric implements Metric<String> {
	
	private final boolean caseSensitive;
	
	public JaroWinklerMetric() {
		this(true);
	}
	
	public JaroWinklerMetric(boolean caseSensitive) {
		this.caseSensitive = caseSensitive;
	}

	@Override public double distance(String lhs, String rhs) {
		final String srt, lng;
		if (lhs.length() < rhs.length()) {
			srt = lhs;
			lng = rhs;
		} else {
			srt = rhs;
			lng = lhs;
			//if (lhs.equals(rhs))
				//return 0.0;
		}
		
		final int maxDistance = srt.length() / 2;
		int m = 0, t = 0; 
		int p = -1;
		for (int i = 0; i < lng.length(); i++) {
			char c = lng.charAt(i);
			for (int j = Math.max(0, i - maxDistance); j < Math.min(srt.length(), i + maxDistance); j++) {
				if (equals(c,srt.charAt(j))) {
					m++;
					if (p != -1 && j < p)
						t++; 
					p = j;
					break;
				}
			}
		}

		if (m == 0)
			return 1.0;
		else
			return 1 - ((m / (double) lng.length()) + (m / (double) srt.length()) + ((m - t) / (double) m)) / 3.0;
	}
	
	private final boolean equals(char lhs, char rhs) {
		if (caseSensitive)
			return lhs == rhs;
		else
			return Character.toLowerCase(lhs) == Character.toLowerCase(rhs);
	}

}
